// 扩展1. 异常规则说明

#include <iostream>

class MyException1
{
private:
  std::string msg;

public:
  MyException1(const char *str)
  {
    msg = str;
  }
  MyException1(const MyException1 &obj) : msg(obj.msg)
  {
    std::cout << "MyException1拷贝构造函数" << std::endl;
  }
  // virtual 通常是虚函数 继承是重写
  virtual ~MyException1()
  {
    std::cout << "MyException1析构函数" << std::endl;
  }

  const char *what()
  {
    // std::cout << msg << std::endl;
    return msg.c_str();
  }
};

class MyException2 : public std::exception
{
private:
  /* data */
public:
  MyException2(/* args */);
  ~MyException2();
  // 重写（覆盖）基类虚函数what
  const char *what()
  {
    return "MyException2 error message";
  }
};

MyException2::MyException2(/* args */)
{
}
// MyException2::MyException2(const MyException2 &)
// {
// }

MyException2::~MyException2()
{
}

// void fun(int n) throw();
// void fun(int n) noexcept;
// void fun(int n);// 可以抛出任意类型错误
// void fun(int n) throw(const char *);// 允许抛出V指定的异常类型

// 函数默认值在声明时设置
// void fun(int n = 0) throw(const char *, int, MyException1, MyException2, std::exception);
void fun(int n) throw(const char *, int, MyException1, MyException2, std::exception);

int main(void)
{
  try
  {
    // fun(); // const char *
    // fun(0); // const char *
    fun(1); // int
    // fun(2); // MyException1
    // fun(3); // MyException2
    // fun(4); // std::exception
    // fun(5); // "success"
  }
  catch (const char *e)
  {
    std::cerr << e << std::endl;
  }
  catch (int e)
  {
    std::cerr << "int err! "
              << "e : " << e << std::endl;
  }
  catch (MyException1 &e)
  {
    std::cerr << e.what() << std::endl;
  }
  catch (MyException2 &e)
  {
    std::cerr << e.what() << std::endl;
  }
  catch (std::exception &e)
  {
    std::cerr << e.what() << std::endl;
  }
  catch (...)
  {
    std::cerr << "error!" << std::endl;
  }
  printf("----------end------------\n");
  return 0;
}

// throw()、noexcept  函数不允许抛出任何类型异常， 如果throw会报错 terminate called after throwing an instance of 'int'
// 抛出异常规格说明中不存在的异常类型报错; 已终止，退出代码: 3   terminate called after throwing an instance of 'std::exception'
// 声明和定义的throw必须一致 好麻烦  error: declaration of 'void fun(int)' has a different exception specifier
void fun(int n) throw(const char *, int, MyException1, MyException2, std::exception)
// void fun(int n)
{
  std::cout << "n : " << n << std::endl;
  if (0 == n)
  {
    throw "default value 0!"; // const char *
  }
  else if (1 == n)
  {
    throw 1; //int
  }
  else if (2 == n)
  {
    throw MyException1("MyException1 error message"); // MyException1
  }
  else if (3 == n)
  {
    throw MyException2(); // MyException2
  }
  else if (4 == n)
  {
    throw std::exception();
  }
  else
  {
    std::cout << "success" << std::endl;
  }
}